Type inference in 13.11, local declarations, exception monitoring at tag level, and function extensionality
Several topics here, all arising from my thinking about ISE's proposals for type inference.
Type inference in functional languages such as Haskell, goes naturally with a language where you do not have a locals declaration block. This goes against Eiffel style, so I think type inference should be confined to Eiffel Studio (a sort of extended intellisense).
Thinking about it, I realized we can already dispense with local declarations in 13.11 (and for some considerable time before that).
Haskell has a wonderful program called QuickCheck. It is a bit like our Autotest, except instead of operating on contracts, it operates on QuickCheck properties. These can express general algebraic laws, whcih can't be written in Haskell. As a result, the programmer has to write these laws aside from the source code. Not so good.
Wouldn't it be great if we could use class invariants for checking algebraic laws? Maybe even prove two versions of a function are extensionally equal (then we can laugh even louder at
Now, this is using the creation procedure to check the invariant clauses. This could easily get very expensive (which is why I used NATURAL_8 rather than NATURAL). What we really want is invariants that are monitored by Autotest, but not by our normal workbench-mode debugging runs.
Eric Bezault has long advocated being able to selectively monitor assertions by selecting on the tag (a regular expression to select tags would be nice). I've always thought this to be an excellent idea - we need it. And this example feeds fuel to the fire, I think.
Shouldn't it be lifted as a postcondition?
It's not clear whether a class invariant is a good choice (not only in this example, but also in general). I believe in many cases it can be expressed as a postcondition instead. The class invariants may be good when they can be violated. If they cannot be violated, they express stricter properties and therefore may be expressed in the stricter form of postconditions. In this example, the postcondition of
twice_plus_one_take_2
will beensure Result = twice_plus_one (a_natural)
And this does not seem too expensive now compared to the class invariant case.True. But the postcondition
True. But the postcondition only gets checked on specific values that it gets called on. AutoTest can check values at random. The class I coded tests all possible values, and this technique is available for all functions where the domain can be exhaustively enumerated in a reasonable time.
Anyway, that was merely an after-thought that occured to me as I started to write a demo that local blocks aren't needed. Not that I approve of the style.
It depends what class invariant is about
I think a class invariant is about properties of an object. The postcondition better reflects the properties of the features instead. In your example, the argument type can be easily changed into a formal generic type (e.g.,
NUMERIC
) if the property we talk about is coded in the postcondition. But it cannot be expressed in the invariant in this case. In this sense the postconditions are more universal as they apply to all possible argument values even if they cannot be finitely enumerated.In fact, as soon as the compiler (or some other tool) detects that there is a postcondition that applies to the finite number of argument values, it can automatically add an invariant clause that performs the iteration over all these values.
That's a nice idea.